package org.example.sdpback.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.example.sdpback.domain.entity.User;
import org.example.sdpback.domain.po.UserPO;
import org.example.sdpback.domain.vo.UserVO;
import org.example.sdpback.mapper.UserMapper;
import org.example.sdpback.service.UserService;
import org.example.sdpback.utils.JwtUtil;
import org.example.sdpback.utils.MD5Util;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final StringRedisTemplate redisTemplate;

    /**
     * 根据id获取用户
     * @param id
     * @return
     */
    public User getUserById(Long id) {
        return getById(id);
    }

    /**
     * 注册用户
     * @param username
     * @param password
     */
    @Override
    public void register(String username, String password) {
        //TODO 1.解密前端加密的数据

        //2.解密后的密码再加密
        String salt = MD5Util.getSalt();
        password = MD5Util.md5(password, salt);

        //3.构建实体对象存入数据库
        User user = new User();
        user.setUsername(username);
        user.setPassword(password);
        user.setSalt(salt);
        user.setEmail(username + "@example.com");
        user.setMobile("13112341234");
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        save(user);
    }

    /**
     * 根据用户名获取用户
     * @param username
     * @return
     */
    @Override
    public User getUserByName(String username) {
        return  lambdaQuery().eq(User::getUsername, username).one();
    }

    /**
     * 校验密码是否正确
     * @param user
     * @param password
     * @return
     */
    @Override
    public Boolean checkPassword(User user, String password) {
        // 密码是否正确
        String salt = user.getSalt();
        String passwordHash = user.getPassword();
        return MD5Util.md5(password, salt).equals(passwordHash);
    }

    /**
     * 修改密码
     * @param user
     * @param password
     */
    @Override
    public void modifyPassword(User user, String password) {
        String salt = MD5Util.getSalt();
        String newPasswordHash = MD5Util.md5(password, salt);
        user.setPassword(newPasswordHash);
        user.setSalt(salt);
        user.setUpdateTime(LocalDateTime.now());
        updateById(user);
        // 修改密码需要删除redis中的token
        redisTemplate.opsForValue().getOperations().delete(user.getUsername());
    }

    /**
     * 初始化密码
     * @param user
     */
    @Override
    public void initPassword(User user) {
        String salt = MD5Util.getSalt();
        String initPassword = MD5Util.initPassword(salt);
        user.setPassword(initPassword);
        user.setSalt(salt);
        updateById(user);
        // 修改密码需要删除redis中的token
        redisTemplate.opsForValue().getOperations().delete(user.getUsername());
    }

    /**
     * 登录
     * @param username
     * @param password
     * @return
     */
    @Override
    public UserVO login(String username, String password) {
        //登陆获取用户
        User user = getUserByName(username);
        if (user == null) {
            throw new RuntimeException("用户名不存在！");
        }
        // 校验密码
        if (!checkPassword(user, password)){
            throw new RuntimeException("密码错误！");
        };

        // 生成token返回前端
        String token = JwtUtil.getToken(user);
        UserVO userVO = new UserVO();
        BeanUtil.copyProperties(user, userVO);
        userVO.setUserId(user.getId());
        userVO.setUserName(username);
        userVO.setToken(token);

        // 将token存入redis
        redisTemplate.opsForValue().set(username, token, 1, TimeUnit.DAYS);
        return userVO;
    }

    /**
     * 更新用户信息
     * @param user
     */
    @Override
    public void updateUser(User user) {
        user.setUpdateTime(LocalDateTime.now());
        updateById(user);
    }

    /**
     * 校验登录是否为当前用户
     */
    @Override
    public void checkCurrentUser(UserPO userPO, User tokenUser) {

        User userById = getUserById(tokenUser.getId());
        userById.setNickname(userPO.getNickname());
        userById.setEmail(userPO.getEmail());
        userById.setMobile(userPO.getMobile());
        updateUser(userById);
    }

    /**
     * 查询用户列表
     * @param username
     * @return
     */
    @Override
    public List<User> getUserList(String username) {

        if (username == null) {
            return list();
        }
        return lambdaQuery().like(User::getUsername, username).list();
    }
}
